// 启动时指定文件名，当有新连接时就把文件内容完整的发给对方。
// 版本二，一块一块发送文件，用于解决版本一内存过多问题，
// 新建连接时发送 64KiB 数据，等这块数据发送完毕时再发送 64KiB 数据，如此往复直到全部发完。
#include <muduo/base/Logging.h>
#include <muduo/net/EventLoop.h>
#include <muduo/net/TcpServer.h>
#include <stdio.h>

using namespace muduo;
using namespace muduo::net;

const int kBufSize = 64 * 1024;
const char *g_file = NULL;

void
OnHighWaterMark(const TcpConnectionPtr &conn, size_t len) {
	LOG_INFO << "HighWaterMark " << len;
}

void OnConnection(const TcpConnectionPtr &conn) {
	LOG_INFO << "FileServer - " << conn->peerAddress().toIpPort() << " -> "
	         << conn->localAddress().toIpPort() << " is "
	         << (conn->connected() ? "UP" : "DOWN");
	if (conn->connected()) {
		LOG_INFO << "FileServer - Sending file " << g_file
		         << " to " << conn->peerAddress().toIpPort();
		conn->setHighWaterMarkCallback(OnHighWaterMark, 64 * 1024);
		
		FILE *fp = ::fopen(g_file, "rb");
		if (fp) {
			conn->setContext(fp);
			char buf[kBufSize];
			size_t nread = ::fread(buf, 1, sizeof(buf), fp);
			conn->send(buf, static_cast<int>(nread));
		} else {
			conn->shutdown();
			LOG_INFO << "FileServer - no such file";
		}
	} else {
		if (!conn->getContext().empty()) {
			FILE *fp = boost::any_cast<FILE*>(conn->getContext());
			if (fp)
				::fclose(fp);
		}
	}
}

void 
OnWriteComplete(const TcpConnectionPtr &conn) {
	FILE *fp = boost::any_cast<FILE*>(conn->getContext());
	char buf[kBufSize];
	size_t nread = ::fread(buf, 1, sizeof(buf), fp);
	if (nread > 0) {
		conn->send(buf, static_cast<int>(nread));
	} else {
		::fclose(fp);
		fp = NULL;
		conn->setContext(fp);
		conn->shutdown();
		LOG_INFO << "FileServer - done";
	}
}

int 
main(int argc, char **argv) {
	LOG_INFO << "pid = " << getpid();
	if (argc > 1) {
		g_file = argv[1];

		EventLoop loop;
		InetAddress listenAddr(2021);
		TcpServer server(&loop, listenAddr, "FileServer");
		server.setConnectionCallback(OnConnection);
		server.setWriteCompleteCallback(OnWriteComplete);
		server.start();
		loop.loop();
	} else {
		fprintf(stderr, "Usage %s file_for_downloading\n", argv[0]);
	}
}
